#include "rcc.h"
#include "misc.h"
#include "USART.h"
#include "stm32f10x_exti.h"
#include "main.h"
#include "serial.h"
#include "nvic.h"
#include "rtcSleep.h"
#include "digital.h"
#include "main.h"

#include "CC1101/CC1101.H"
#include "cc1101/higerCC1101.h"

#define RELOAD_VAL_SYSTIM  0xffffffff

//=========================== defines =========================================
//#define RADIOTIMER_OVERFLOW_PERIOD       20000
//#define RADIOTIMER_COMPARE_PERIOD        3000
//#define RADIOTIMER_NUM_COMPARES             4
#define RADIOTIMER_OVERFLOW_PERIOD       35000
#define RADIOTIMER_COMPARE_PERIOD        700//200--6ms;600--19ms;35000--1000ms
#define RADIOTIMER_NUM_COMPARES          45

//=========================== variables =======================================
typedef struct {
    uint8_t  num_compares_left;
    uint16_t last_compare_val;
} app_vars_t;

app_vars_t app_vars;

typedef struct {
    uint16_t num_overflow;
    uint16_t num_compare;
} app_dbg_t;

app_dbg_t app_dbg;


digitalPin *redLed, *greenLed, *blueLed;

uint32_t ullTime32_incr = 0;

//=========================== prototypes ======================================
void cb_overflow(void);
void cb_compare(void);

uint32_t portGetTickCnt( void )
{
    return ullTime32_incr;
}

/********************************************************
 * board.c
 *
********************************************************/
void board_sleep() {
    DBGMCU_Config( DBGMCU_STOP, ENABLE );
    // Enable PWR and BKP clock
    RCC_APB1PeriphClockCmd( RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE );
    // Desable the SRAM and FLITF clock in Stop mode
    RCC_AHBPeriphClockCmd( RCC_AHBPeriph_SRAM | RCC_AHBPeriph_FLITF, DISABLE );
    // enter sleep mode
    __WFI();
}

void board_reset(){
    NVIC_SystemReset();
}

/*******************************************************/
void NVIC_init(void)
{
#ifdef  VECT_TAB_RAM
    /* Set the Vector Table base location at 0x20000000 */
    NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else  /* VECT_TAB_FLASH  */
    /* Set the Vector Table base location at 0x08000000 */
    NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
}

//=========================== private =========================================
void board_enableHardFaultExceptionHandler(){
    // Configures:
    //    bit9. stack alignment on exception entry
    //    bit4. enables faulting
    //    bit3. unaligned access traps
    SCB->CCR = 0x00000210;
}

int main( void )
{
    //    RCC_Configuration();//开启CPU默认的一些时钟等
    //    //Set the Vector Table base location
    //    NVIC_init();
    rccInit();

    //2 bits for Preemption Priority and 2 bits for Sub Priority
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    board_enableHardFaultExceptionHandler();

    serialInit();
    CC_Init();

    redLed = digitalInit( GPIOC, GPIO_Pin_9 );
    greenLed = digitalInit( GPIOC, GPIO_Pin_6 );
    blueLed = digitalInit( GPIOA, GPIO_Pin_8 );

    // kick off first compare
    app_vars.num_compares_left  = RADIOTIMER_NUM_COMPARES-1;
    app_vars.last_compare_val   = RADIOTIMER_COMPARE_PERIOD;

    // prepare radiotimer
    radiotimer_setOverflowCb(cb_overflow);
    radiotimer_setCompareCb(cb_compare);

    radiotimer_start( RADIOTIMER_OVERFLOW_PERIOD );
    radiotimer_schedule(app_vars.last_compare_val);

    while(1) {
        board_sleep();
        digitalTogg(blueLed);
    }
    return 0;
}

/********************************************************
 * callback
 *
********************************************************/

void cb_overflow(void) {

    //   // toggle pin
    //   debugpins_frame_toggle();

    //   // switch radio LED on
    //   leds_error_toggle();
    digitalTogg(redLed);

    // reset the counter for number of remaining compares
    app_vars.num_compares_left  = RADIOTIMER_NUM_COMPARES;
    app_vars.last_compare_val   = RADIOTIMER_COMPARE_PERIOD;
    radiotimer_schedule(app_vars.last_compare_val);

    // increment debug counter
    app_dbg.num_overflow++;
}

void cb_compare(void) {

    //   // toggle pin
    //   debugpins_slot_toggle();

    //   // toggle radio LED
    //   leds_radio_toggle();
    digitalTogg(greenLed);

    // schedule a next compare, if applicable
    app_vars.last_compare_val += RADIOTIMER_COMPARE_PERIOD;
    app_vars.num_compares_left--;
    if (app_vars.num_compares_left>0) {
        radiotimer_schedule(app_vars.last_compare_val);
    } else {
        radiotimer_cancel();
    }

    // increment debug counter
    app_dbg.num_compare++;
}
/*******************************************************/

/********************************************************
 * ISR 入口
 *
********************************************************/
//系统tickcount中断
void SysTick_Handler(void) {
    runFeedIWDG();
    if (ullTime32_incr >= RELOAD_VAL_SYSTIM) {
        ullTime32_incr = 0;
    } else {
        ullTime32_incr++;
    }
}

void RTCAlarm_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line17) != RESET)
    {
        EXTI_ClearITPendingBit(EXTI_Line17);
        radiotimer_isr();
    }
}

void RTC_IRQHandler(void)
{
    if(RTC_GetFlagStatus(RTC_IT_ALR) != RESET)
    {
        RTC_ClearITPendingBit(RTC_IT_ALR);      //Clear RTC Alarm interrupt pending bit
        RTC_WaitForLastTask();                  //Wait until last write operation on RTC registers has finished
    }
}

void HardFault_Handler(void) {
    //    FET_PANIC;
    board_reset();
    //    while (1)
    ;
}

void MemManage_Handler(void) {
    //    FET_PANIC;
    while (1)
        ;
}

void BusFault_Handler(void) {
    //    FET_PANIC;
    while (1)
        ;
}

void UsageFault_Handler(void) {
    //    FET_PANIC;
    while (1)
        ;
}

void reset_wait(void) {
    //    FET_PANIC;
    while (1)
        ;
}

/********************************************************/
#if 0
//__disable_irq()
__asm void CPSID_I(void)
{
    PUSH {lr}
    cpsid i
            POP {PC}
}

//__disable_fault_irq()
__asm void CPSID_F(void)
{
    PUSH {lr}
    cpsid f
            POP {PC}
}

//__enable_irq()
__asm void CPSIE_I(void)
{
    PUSH {lr}
    cpsie i
            POP {PC}
}
#endif

__asm void nop(void)
{
    PUSH {lr}
    nop
            nop
            nop
            nop
            POP {PC}
}
